//
//  DrawCubeDemoVC.m
//  FilamentDemo
//
//  Created by 8000 on 2020/5/1.
//  Copyright © 2020 tencent. All rights reserved.
//

#import "DrawCubeWithMaterialDemoVC.h"
#import "FilamentView.h"
#import "FilamentRender.h"
#import "FilamentConvenientHeader.h"
#import "Entities.h"

@interface DrawCubeWithMaterialDemoVC ()
@property (nonatomic, assign) Material *litMat;
@property (nonatomic, strong) NSData *litMatData;

@property (nonatomic, assign) Material *unLitMat;
@property (nonatomic, strong) NSData *unLitMatData;

@property (nonatomic, assign) IndirectLight *indirectLight;
@property (nonatomic, assign) Entity sun;
@property (nonatomic, assign) image::KtxBundle *iblBundle; //内部自动释放
@property (nonatomic, assign) Texture *iblTexture;
@property (weak, nonatomic) IBOutlet UISegmentedControl *modeSw;

@end

@implementation DrawCubeWithMaterialDemoVC
{
    float3 *_vertexs;
    uint16_t *_indices;
    Entity _cubeEntity;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view bringSubviewToFront:_modeSw];
	_litMatData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"drawCubeWithMaterialDemo_lit.filamat" ofType:nil]];
	_litMat = Material::Builder().package([_litMatData bytes], [_litMatData length])
                                 .build(*self.render.engine);
    
    _unLitMatData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"drawCubeWithMaterialDemo_unlit.filamat" ofType:nil]];
    _unLitMat = Material::Builder().package([_unLitMatData bytes], [_unLitMatData length])
                                   .build(*self.render.engine);   
	
    int vertexCount = 8;
    int indicesCount = 36;
    _vertexs = new float3[vertexCount]{
        float3{-0.1,  0.1, 0.1},
        float3{ 0.1,  0.1, 0.1},
        float3{ 0.1, -0.1, 0.1},
        float3{-0.1, -0.1, 0.1},

        float3{-0.1, 0.1, -0.1},
        float3{ 0.1, 0.1, -0.1},
        float3{ 0.1,-0.1, -0.1},
        float3{-0.1,-0.1, -0.1},
    };
    
    _indices = new uint16_t[indicesCount]{
        0,3,2, //前
        0,2,1,

        5,6,7, //后
        5,7,4,

        0,4,7, //左
        0,7,3,

        1,2,6, //右
        1,6,5,

        4,0,1, //顶
        4,1,5,

        6,2,3, //底
        6,3,7
    };

	VertexBuffer *vb = VertexBuffer::Builder().vertexCount(vertexCount)
											  .bufferCount(1)
											  .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3, 0, sizeof(_vertexs[0]))
											  .build(*self.render.engine);

    vb->setBufferAt(*self.render.engine,
                    0,
                    VertexBuffer::BufferDescriptor(_vertexs,
                                                   vertexCount * sizeof(_vertexs[0]), nullptr));


    IndexBuffer *ib = IndexBuffer::Builder().indexCount(indicesCount)
											.bufferType(IndexBuffer::IndexType::USHORT)
											.build(*self.render.engine);

    ib->setBuffer(*self.render.engine, IndexBuffer::BufferDescriptor(_indices,
																 indicesCount * sizeof(uint16_t), nullptr));
    _cubeEntity = EntityManager::get().create();
    
    
    Box aabb = RenderableManager::computeAABB(_vertexs, _indices, vertexCount);
    filament::RenderableManager::Builder(1)
                        .geometry(0, filament::RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, indicesCount)
                        .boundingBox(aabb)
                        .build(*self.render.engine, _cubeEntity);

    self.render.scene->addEntity(_cubeEntity);
  
    [self setupIbl];
    
    [self switchToLit];
}

- (void)setupIbl{
    
    //ktx: 保存了可以直接传给GPU的纹理数据
    NSData* data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"ibl.ktx" ofType:nil]];
    
    _iblBundle = new image::KtxBundle((uint8_t *)[data bytes], (uint32_t)data.length);
    filament::math::float3 harmonics[9];
    _iblBundle->getSphericalHarmonics(harmonics);
    //会自动释放
    _iblTexture = image::ktx::createTexture(self.render.engine, _iblBundle, false);

    _indirectLight = IndirectLight::Builder()
         .reflections(_iblTexture) //反射度
         .irradiance(3, harmonics) //辐照度
         .intensity(3000) //亮度
         .build(*self.render.engine);
     self.render.scene->setIndirectLight(_indirectLight);

    _sun = EntityManager::get().create();
    LightManager::Builder(LightManager::Type::SUN)
        .direction({-1, -1, -1})
        .build(*self.render.engine, _sun);
    self.render.scene->addEntity(_sun);
}

- (void)dealloc{
    [self.render removeEntity:_cubeEntity];
    [self.render removeEntity:_sun];
    if (_vertexs != nullptr) {
        delete _vertexs;
        _vertexs = nullptr;
    }
    if (_indices != nullptr) {
        delete _indices;
        _indices = nullptr;
    }
    
    self.render.engine->destroy(_indirectLight);
    self.render.engine->destroy(_iblTexture);
}

- (IBAction)onSwitchMat:(UISegmentedControl *)sender {
    //lit
    if (sender.selectedSegmentIndex == 0) {
        [self switchToLit];
    }else{ //unlit
        [self switchToUnlit];
    }
}

- (void)switchToUnlit{
    MaterialInstance *matInstance = _unLitMat->getDefaultInstance();
    matInstance->setParameter("baseColor", filament::RgbaType::sRGB, float4{1,0,0,1});
    RenderableManager& rm = self.render.engine->getRenderableManager();
    rm.setMaterialInstanceAt(rm.getInstance(_cubeEntity),
                             0, //primitiveIndex
                             matInstance);
}

- (void)switchToLit{
    MaterialInstance *matInstance = _litMat->getDefaultInstance();
    matInstance->setParameter("baseColor", filament::RgbaType::sRGB, float4{0,1,0,1});
    RenderableManager& rm = self.render.engine->getRenderableManager();
    rm.setMaterialInstanceAt(rm.getInstance(_cubeEntity), 0, matInstance);
}

@end
